package com.mingyuan.library.application.lending.presentation;

import com.mingyuan.library.domain.lending.book.model.entity.AvailableBook;
import com.mingyuan.library.infra.lending.book.repository.AvailableBookRepository;
import com.mingyuan.library.domain.lending.patron.event.BookHoldFailed;
import com.mingyuan.library.domain.lending.patron.event.BookPlacedOnHoldEvents;
import com.mingyuan.library.domain.lending.patron.model.aggregate.Patron;
import com.mingyuan.library.domain.lending.patron.model.valueobject.HoldDuration;
import com.mingyuan.library.domain.lending.patron.repository.PatronRepository;
import com.mingyuan.library.infra.common.utils.validate.ValidatorUtil;
import com.mingyuan.library.provider.lending.model.command.PlaceHoldCommand;
import com.mingyuan.library.provider.lending.model.command.PlaceOnHoldCommand;
import com.mingyuan.library.provider.lending.model.dto.PatronProfileDTO;
import com.mingyuan.library.provider.lending.model.query.PatronProfileQuery;
import com.mingyuan.library.provider.lending.presentation.PatronProfilePresentation;
import io.vavr.control.Either;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.util.UUID;

import static io.vavr.API.*;
import static io.vavr.Patterns.$Left;
import static io.vavr.Patterns.$Right;

/**
 * 读者档案演示层实现逻辑实现
 *
 * @author yangzk
 * @version 1.0.0
 * @date 2024.01.05 19:05
 */
@Slf4j
@Service
public class PatronProfilePresentationImpl implements PatronProfilePresentation {

    /**
     * 可用图书仓储接口
     */
    @Resource
    private AvailableBookRepository availableBookRepository;
    /**
     * 读者仓储接口
     */
    @Resource
    private PatronRepository patronRepository;

    @Override
    public PatronProfileDTO findPatronProfile(PatronProfileQuery patronProfileQuery) {
        // 1. 参数校验
        ValidatorUtil.valid(patronProfileQuery);
        return null;
    }

    @Override
    public Boolean placeOnHold(PlaceHoldCommand placeHoldCommand) {
        // 1. 参数校验
        ValidatorUtil.valid(placeHoldCommand);
        // 查询图书是否可以预定
        AvailableBook availableBook = this.availableBookRepository.findAvailableBookBy(placeHoldCommand.getBookId());
        // 查询读者信息是否存在
        Patron patron = this.patronRepository.find(placeHoldCommand.getPatronId());
        // 读者预定图书
        Either<BookHoldFailed, BookPlacedOnHoldEvents> result = patron.placeOnHold(availableBook, HoldDuration.getHoldDuration(placeHoldCommand.getNumberOfDays()));
        // 根据预定逻辑结果发布事件
        return Match(result).of(
                Case($Left($()), this::publishEvents),
                Case($Right($()), this::publishEvents)
        );
    }

    @Override
    public Boolean placeOnHold(PlaceOnHoldCommand placeOnHoldCommand) {
        // 1. 参数校验
        ValidatorUtil.valid(placeOnHoldCommand);
        return null;
    }

    /**
     * 发布成功事件
     * @author yangzk
     * @param placedOnHold 预定成功
     * @date 2024/1/16 14:00
     **/
    private Boolean publishEvents(BookPlacedOnHoldEvents placedOnHold) {
        patronRepository.publish(placedOnHold);
        return Boolean.TRUE;
    }
    /**
     * 发布失败事件
     * @author yangzk
     * @param bookHoldFailed 预定失败信息
     * @date 2024/1/16 14:01
     * @return
     **/
    private Boolean publishEvents(BookHoldFailed bookHoldFailed) {
        patronRepository.publish(bookHoldFailed);
        return Boolean.FALSE;
    }

}
